package org.jeecg.modules.hc.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.boot.starter.lock.annotation.JLock;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.hc.constant.RedisConstant;
import org.jeecg.modules.hc.entity.HcMerchant;
import org.jeecg.modules.hc.entity.HcMerchantData;
import org.jeecg.modules.hc.entity.HcMerchantSettlement;
import org.jeecg.modules.hc.enums.HcMerchantSettlementTypeEnum;
import org.jeecg.modules.hc.enums.HcSyncMerchantSettlementTypeEnum;
import org.jeecg.modules.hc.mapper.HcMerchantSettlementMapper;
import org.jeecg.modules.hc.mapper.HcOrderMerchantMapper;
import org.jeecg.modules.hc.service.IHcMerchantService;
import org.jeecg.modules.hc.service.IHcMerchantSettlementService;
import org.jeecg.modules.hc.utils.HcUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * @Description: 商户结算
 * @Author: jeecg-boot
 * @Date: 2023-02-17
 * @Version: V1.0
 */
@Service
@Slf4j
public class HcMerchantSettlementServiceImpl extends ServiceImpl<HcMerchantSettlementMapper, HcMerchantSettlement> implements IHcMerchantSettlementService {

    @Resource
    private HcOrderMerchantMapper hcOrderMerchantMapper;

    @Autowired
    private HcMerchantSettlementMapper hcMerchantSettlementMapper;

    @Lazy
    @Autowired
    private HcMerchantSettlementServiceImpl hcMerchantSettlementService;

    @Lazy
    @Autowired
    private IHcMerchantService hcMerchantService;

    @Override
    public IPage<HcMerchantSettlement> pageList(Page<HcMerchantSettlement> page, HcMerchantSettlement param) {
        IPage<HcMerchantSettlement> pageList = hcMerchantSettlementMapper.pageList(page, param);

        for (HcMerchantSettlement record : pageList.getRecords()) {
            try {
                hcMerchantSettlementService.syncMerchantSettlement(record.getId(), HcSyncMerchantSettlementTypeEnum.TODAY);
            } catch (Exception e) {
                log.error(JSON.toJSONString(record));
                e.printStackTrace();
            }
        }

        return hcMerchantSettlementMapper.pageList(page, param);
    }

    @JLock(lockKey = "'" + RedisConstant.SYNC_MERCHANT_SETTLEMENT_LOCK + "'.concat(#merchantId)")
    @Transactional(rollbackFor = Exception.class)
    public List syncMerchantSettlement(String merchantId, HcSyncMerchantSettlementTypeEnum typeEnum) throws ParseException {
        List result = new ArrayList();

        //默认跑昨天的数据，但是触发方法一定要在当天的18:00之后才是跑的昨天的数据
        Calendar maxCalendar = Calendar.getInstance();
        Calendar minCalendar = Calendar.getInstance();
        int d = 1;

        if (HcSyncMerchantSettlementTypeEnum.TODAY.equals(typeEnum)) {
            //如果跑当天的数据，需要根据当前时间是否在18:00:00前后来获取时间范围
            maxCalendar.setTime(DateUtils.parseDate(HcUtils.getYongShanTuanTime().getString("endTime"), "yyyy-MM-dd"));
        } else if (HcSyncMerchantSettlementTypeEnum.ALL.equals(typeEnum)) {
            //这里是跑所有日期的数据
            //获取商家最早订单时间
            HcMerchantData hcMerchantData = hcOrderMerchantMapper.getHcMerchantData(merchantId);

            if (hcMerchantData == null) {
                log.error("商家无订单数据，id：{}", merchantId);
                return result;
            }

            minCalendar.setTime(hcMerchantData.getMinDate());

            d = DateUtils.dateDiff('d', DateUtils.parseCalendar(DateUtils.formatDate(maxCalendar, "yyyy-MM-dd"), "yyyy-MM-dd"), DateUtils.parseCalendar(DateUtils.formatDate(minCalendar, "yyyy-MM-dd"), "yyyy-MM-dd"));

            //如果当前日期在18:00点后，需要增加一天
            if (maxCalendar.getTime().after(DateUtils.parseDate(DateUtils.formatDate(maxCalendar, "yyyy-MM-dd") + " 18:00:00", "yyyy-MM-dd HH:mm:ss"))) {
                d++;
                maxCalendar.add(Calendar.DAY_OF_MONTH, 1);
            }

            //如果最早订单时间在18:00前，需要增加一天
            if (minCalendar.getTime().before(DateUtils.parseDate(DateUtils.formatDate(minCalendar, "yyyy-MM-dd") + " 18:00:00", "yyyy-MM-dd HH:mm:ss"))) {
                d++;
            }
        }

        for (int i = 0; i < d; i++) {
            String beginTime = "";
            String endTime = DateUtils.formatDate(maxCalendar, "yyyy-MM-dd") + " 18:00:00";

            Calendar instance = Calendar.getInstance();
            instance.setTime(maxCalendar.getTime());
            instance.add(Calendar.DAY_OF_MONTH, -1);
            beginTime = DateUtils.formatDate(instance, "yyyy-MM-dd") + " 18:00:01";

            HcMerchantData merchantDataRecord = hcOrderMerchantMapper.getMerchantDataRecord(merchantId, beginTime, endTime);

            HcMerchantSettlement one = hcMerchantSettlementService.getOne(new QueryWrapper<HcMerchantSettlement>()
                    .select("ifnull(sum(SETTLEMENT_AMOUNT), 0) as SETTLEMENT_AMOUNT")
                    .eq("MERCHANT_ID", merchantId)
                    .eq("TYPE", HcMerchantSettlementTypeEnum.CHANGE.getValue())
                    .between("CREATE_TIME", beginTime, endTime)
            );

            if (merchantDataRecord == null) {
                merchantDataRecord = new HcMerchantData().setTodayIncome(new BigDecimal(0));
            }

            merchantDataRecord.setTodayIncome(merchantDataRecord.getTodayIncome().add(one.getSettlementAmount()));

            HcMerchantSettlement hcMerchantSettlement = this.getOne(new QueryWrapper<HcMerchantSettlement>()
                    .eq("MERCHANT_ID", merchantId)
                    .eq("SETTLEMENT_DATE", DateUtils.formatDate(maxCalendar, "yyyy-MM-dd"))
            );

            if (hcMerchantSettlement == null) {
                HcMerchantSettlement merchantSettlement = new HcMerchantSettlement()
                        .setType(HcMerchantSettlementTypeEnum.UNSETTLED)
                        .setMerchantId(merchantId)
                        .setSettlementDate(maxCalendar.getTime())
                        .setSettlementAmount(merchantDataRecord.getTodayIncome());

                if (HcSyncMerchantSettlementTypeEnum.YESTERDAY.equals(typeEnum)) {
                    merchantSettlement.setCreateBy("system");
                    merchantSettlement.setCreateTime(new Date());
                }

                this.save(merchantSettlement);
            } else {
                if (hcMerchantSettlement.getType() == HcMerchantSettlementTypeEnum.UNSETTLED) {
                    this.updateById(hcMerchantSettlement.setSettlementAmount(merchantDataRecord.getTodayIncome()));
                } else {
                    //如果状态不是未结算并且结算金额和计算的金额不一致，则返回，方便去修改数据
                    if (hcMerchantSettlement.getSettlementAmount().compareTo(merchantDataRecord.getTodayIncome()) != 0) {
                        HcMerchant hcMerchant = hcMerchantService.getById(merchantId);

                        Map map = new HashMap();
                        map.put("结算ID", hcMerchantSettlement.getId());
                        map.put("商家名称", hcMerchant.getStoreName());
                        map.put("结算数据类型", hcMerchantSettlement.getType().getName());
                        map.put("已结算数据金额", hcMerchantSettlement.getSettlementAmount());
                        map.put("应结算数据金额", merchantDataRecord.getTodayIncome());
                        result.add(map);
                    }
                }
            }

            maxCalendar.add(Calendar.DAY_OF_MONTH, -1);
        }

        return result;
    }
}
